/*
* Copyright @2009-2012 www.happyelements.com, all rights reserved.
* Create date: 2012-7-28
* Piggy Dong
* 董文弈
* wenyi.dong@happyelements.com
*/
package com.happyelements.isolib
{
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * @author dongpiggyi
	 */
	[SWF(backgroundColor="#000000", frameRate="24", width="600", height="600")]
	public class IsoWorld extends Sprite
	{
		public static var bitmapOffset:Point; 
		
		public var _numWorldGrid:int;

		private static var _instance:IsoWorld;

		private var _tileSize:Number;
		
		private var _tileWidth:Number;
		
		private var _tileHeight:Number;
		
		public var tileObjectWarehouse:Vector.<IsoTileObject>;

		public function IsoWorld(entrance:EntranceClass)
		{
			if (!entrance)
			{
				throw new Error("Illigal instantiation of Singleton IsoWorld");
			}
		}

		public static function get instance():IsoWorld
		{
			_instance || (_instance = new IsoWorld(new EntranceClass()));

			return _instance;
		}

		public function initWorld(numWorldGrid:int, tileSize:Number = 10):void
		{
			_numWorldGrid = numWorldGrid;
			_tileSize = tileSize;
			
			_tileWidth = tileSize * 4;
			_tileHeight = tileSize * 2;
			
			tileObjectWarehouse = new Vector.<IsoTileObject>();

			_drawGrid();
		}

		public function getTileObjectPositon(tileObject:IsoTileObject):Point
		{
			var result:Point = IsoUtil.rowColumnToScene(tileObject.rowIndex, tileObject.columnIndex);

			return result;
		}
		
		public function getTileObjectAt(rowIndex:int, columnIndex:int):IsoTileObject
		{
			var areaRect:Rectangle = new Rectangle(rowIndex, columnIndex, 1, 1);
			
			for each(var tileObject:IsoTileObject in tileObjectWarehouse)
			{
				var tileRect:Rectangle = new Rectangle(tileObject.rowIndex, tileObject.columnIndex, tileObject.rows, tileObject.columns);
				
				if (areaRect.intersects(tileRect))
				{
					return tileObject;
				}
			}
			
			return null;
		}
		
		public function addTileObject(tileObject:IsoTileObject):Boolean
		{
			if (canSetTileHere(tileObject))
			{
				storeTileObject(tileObject);
				
				update();
				return true;
			}
			else
			{
				update();
				return false;
			}
		}
		
		public function removeTileObject(tileObject:IsoTileObject):void
		{
			var tileIndex:int = tileObjectWarehouse.indexOf(tileObject);
			
			if (tileIndex == -1)
			{
				throw new Error("The tile object has not in the IsoWorld and cannot be removed");
			}
			
			tileObjectWarehouse.splice(tileIndex, 1);
			
			update();
		}

		public function update():void
		{
			sortTileDepth();
			
			setTilesLayout();
		}

		public function get tileWidth():Number
		{
			return _tileWidth;
		}

		public function get tileHeight():Number
		{
			return _tileHeight;
		}
		
		public function get numWorldGrid():int
		{
			return _numWorldGrid;
		}
		
		private function setTilesLayout():void
		{
			for each (var tile:IsoTileObject in tileObjectWarehouse)
			{
				setTileObjectPosition(tile);
			}
		}

		private function sortTileDepth():void
		{
			tileObjectWarehouse = tileObjectWarehouse.sort(function(comparer:IsoTileObject, baser:IsoTileObject):Number
			{
				var result:Boolean = comparer.rowIndex < baser.rowIndex + baser.rows &&
				comparer.columnIndex < baser.columnIndex + baser.columns;
				
				return (result ? -1 : 1);
			});
		}
		
		public function canSetTileHere(tileObject:IsoTileObject, row:int = -1, column:int = -1):Boolean
		{
			if(row == -1 && column == -1)
			{
				row = tileObject.rowIndex;
				column = tileObject.columnIndex;
			}
			
			var tileRect:Rectangle = new Rectangle(row, column, tileObject.rows, tileObject.columns);
			
			for each (var item:IsoTileObject in tileObjectWarehouse) 
			{
				if (item == tileObject)
				{
					continue;
				}
				
				var itemRect:Rectangle = new Rectangle(item.rowIndex, item.columnIndex, item.rows, item.columns);
				
				if (tileRect.intersects(itemRect))
				{
					return false;
				}
			}
			
			return true;
		}

		private function storeTileObject(tileObject:IsoTileObject):void
		{
			///TODO store this tileObject into the world's warehouse
			
			tileObjectWarehouse.push(tileObject);
		}

		private function setTileObjectPosition(tileObject:IsoTileObject):void
		{
			var tilePosition:Point = getTileObjectPositon(tileObject);
			
			if (tileObject is IsoTileAnimation)
			{
				tilePosition.offset(IsoWorld.bitmapOffset.x, IsoWorld.bitmapOffset.y);
			}
			
			tileObject.setDisplayObjectPosition(tilePosition);
		}
		
		private function _drawGrid():void
		{
			var floorTile:DefaultTileSprite;
			var floorPostion:Point;

			for (var row:int = 0; row < _numWorldGrid; row++)
			{
				for (var column:int = 0; column < _numWorldGrid; column++)
				{
					floorTile = new DefaultTileSprite(row, column);

					floorPostion = getTileObjectPositon(floorTile);

					floorTile.displayObject.x = floorPostion.x;
					floorTile.displayObject.y = floorPostion.y;

					addChild(floorTile.getTypedDisplayObject());
				}
			}
		}
	}
}
class EntranceClass
{
}
